#ifndef GAME_H
#define GAME_H

#include "board.h"
#include "pos.h"
#include "draw.h"
#include "rulechecker.h"
#include "touch.h"
#include "lcd.h"
#include "tcpclient.h"
#include "AIStrategy.h"
#include <sstream> 
#include <iostream>
#include <fstream>  
#include <unistd.h>
#include <vector>
#include <array> 
#include <memory>

using namespace std;

// 菜单区域坐标定义

// 模式区域公用X轴坐标
#define MENU_PATTERN_X1 312
#define MENU_PATTERN_X2 488
// 模式一坐标
#define MENU_PATTERN1_Y1 45
#define MENU_PATTERN1_Y2 112
// 模式二坐标
#define MENU_PATTERN2_Y1 130
#define MENU_PATTERN2_Y2 196
// 模式三坐标
#define MENU_PATTERN3_Y1 213
#define MENU_PATTERN3_Y2 283
// 模式四坐标
#define MENU_PATTERN4_Y1 300
#define MENU_PATTERN4_Y2 365
// 退出按钮坐标
#define MENU_EXIT_X1 620
#define MENU_EXIT_X2 785
#define MENU_EXIT_Y1 380
#define MENU_EXIT_Y2 450

// 定义棋盘快照结构（包含完整棋盘状态+当前回合）
struct BoardSnapshot 
{
    // 9行10列的棋盘数据（与棋盘尺寸一致）
    array<array<ChessDef::pieceID, 10>, 9> boardData;
    bool isRedTurn; // 该快照对应的当前回合（true=红方，false=黑方）
};

class Game
{
    // 成员变量
    Board board;               // 棋盘状态
    RuleChecker ruleChecker;   // 规则校验器（关联棋盘）
    drawBoard drawer;          // 绘制器（使用定义的drawBoard）
    Pos selectedPos;           // 选中的棋子位置（-1,-1表示未选中）
    bool isRedTurn;            // 当前回合（红方true/黑方false）
    bool gameOverFlag;         // 游戏结束标志（照面触发）
    bool redWonFlag;           // 红方胜利标志（照面时用）
    bool isReturnToMenu;       // 判断是不是主动退出
    bool isBackToExitPage;     // 判断是不是回到了主界面
    bool isUndoneInCurrentTurn; // 标记当前回合是否已悔棋（初始false）
    bool skipSaveOnDrawAgree;   //求和同意后是否跳过保存弹窗
    bool isDualMode;            // 双机模式标记
    bool isReturnToMenuDual;    // 双机模式返回菜单标记
    // AI策略相关
    std::unique_ptr<AIStrategy> currentAIStrategy;
    bool isAIMode;                   // 人机模式标记
    bool isReturnToMenuAI;           // 人机模式返回菜单标记
    
    // 人机模式专用函数
    bool processAIMove(const Pos& currentPos);
    bool isAIFunctionButtonClicked(const Point& touchPoint);
    void setAIDifficulty(int difficulty); // 设置AI难度：0-简单，1-中等，2-困难

    bool isDualFunctionButtonClicked(const Point& touchPoint); // 双机模式按钮处理

    // 悔棋相关
    vector<BoardSnapshot> boardHistory;  // 保存历史棋盘快照（含回合信息）
    const int MAX_HISTORY = 4;           // 最多保留4次历史记录
    //联机相关的

    TcpClient tcpClient;       // TCP客户端
    bool isHost;               // 是否为主机（红方）
    bool isNetworkReady;       // 网络连接是否就绪
    std::string serverIp;      // 服务器IP
    int serverPort;            // 服务器端口

    // 辅助函数
    BoardSnapshot getCurrentSnapshot();   // 生成当前棋盘的快照（含回合）
    void restoreFromSnapshot(const BoardSnapshot& snapshot);  // 从快照恢复棋盘状态
    
    // 对局功能函数
    void redoMove(bool isRedButtonClicked);  // 悔棋
    void restartGame();       // 重新开局
    void requestDraw();       // 求和
    void giveUp();            // 认输
    void returnToMenu();      // 返回菜单
    void exitGame();          // 退出游戏

    // 坐标转换与判断函数
    bool convert(int x, int y, Pos &pos);    // 屏幕坐标转数组坐标
    bool isGameOver();                       // 判断游戏是否结束
    void showGameOverAndReturnMenu(Touch* touch);  // 对局结束，进入结束页面
    bool isFunctionButtonClicked(const Point& touchPoint);  // 判断触摸是否落在功能按钮上
    private:
    bool processDualMove(const Pos& currentPos)
    {
        ChessDef::pieceID currentPiece = board.getPieceAt(currentPos);
        
        // 选中阶段
        if (selectedPos.row == -1) 
        {
            if (currentPiece != ChessDef::kong) 
            {
                bool isCurrentRed = ChessDef::isRed(currentPiece);
                // 只能选中己方棋子
                bool canSelect = false;
                if (isHost && isCurrentRed) {
                    canSelect = true; // 红方选红棋
                } else if (!isHost && !isCurrentRed) {
                    canSelect = true; // 黑方选黑棋
                }
                
                if (canSelect) 
                {
                    selectedPos = currentPos;
                    cout << "选中棋子: (" << currentPos.row << "," << currentPos.col << ")" << endl;
                    drawer.draw(board, selectedPos);
                    return false; // 还未完成移动
                }
                else 
                {
                    cout << "不是己方棋子，无法选中" << endl;
                    return false;
                }
            }
            else 
            {
                cout << "点击空位置" << endl;
                if (selectedPos.row != -1) {
                    selectedPos = Pos(-1, -1);
                    drawer.draw(board, selectedPos);
                }
                return false;
            }
        }
        
        // 移动阶段
        cout << "尝试移动: (" << selectedPos.row << "," << selectedPos.col << ")->(" << currentPos.row << "," << currentPos.col << ")" << endl;
        
        if (ruleChecker.isValidMove(selectedPos, currentPos)) 
        {
            BoardSnapshot snapshot = getCurrentSnapshot();
            boardHistory.push_back(snapshot);
            
            board.movePiece(selectedPos, currentPos);
            
            // 发送移动数据
            string moveData = to_string(selectedPos.row) + "," +
                            to_string(selectedPos.col) + "," +
                            to_string(currentPos.row) + "," +
                            to_string(currentPos.col);
            
            if (tcpClient.sendData(moveData)) 
            {
                isRedTurn = !isRedTurn; // 切换回合
                isUndoneInCurrentTurn = false;
                cout << "移动成功，回合切换为: " << (isRedTurn ? "红方" : "黑方") << endl;
                
                // 立即刷新
                selectedPos = Pos(-1, -1);
                drawer.draw(board, selectedPos);
                return true; // 移动完成
            }
            else 
            {
                // 发送失败，回退
                restoreFromSnapshot(snapshot);
                boardHistory.pop_back();
                cout << "移动发送失败，已回退" << endl;
                return false;
            }
        }
        else 
        {
            cout << "移动无效" << endl;
            selectedPos = Pos(-1, -1);
            drawer.draw(board, selectedPos);
            return false;
        }
    }


public:
    // 公共接口
    Game();
    void setGameOver(bool isRedVictory);
    void run();
    bool saveGame(const string& filename = "./save.txt");
    bool loadGame(const std::string& filename = "./save.txt");

private:
    // 输入处理
    void handleInput(const Pos &currentPos, const Point &touchPoint);
};

#endif // GAME_H